/*
 * Copyright (C) 2017 yixun All Rights Reserved.
 * 
 * DepartmentServiceImpl.java
 */
package com.yixun.qfbao.dao.impl;

import com.beust.jcommander.internal.Lists;
import com.yixun.common.page.Page;
import com.yixun.qfbao.dao.DepartmentDao;
import com.yixun.qfbao.mapper.CompanyMapper;
import com.yixun.qfbao.mapper.DepartmentMapper;
import com.yixun.qfbao.mapper.OperationLogMapper;
import com.yixun.qfbao.mapper.PartnerInfoMapper;
import com.yixun.qfbao.model.Department;
import com.yixun.qfbao.model.dto.CompanyDto;
import com.yixun.qfbao.model.dto.DepartmentDto;
import com.yixun.qfbao.model.dto.OperationLogDto;
import com.yixun.qfbao.model.dto.PartnerInfoDto;
import com.yixun.qfbao.model.enums.DelFlagEnum;
import com.yixun.qfbao.model.enums.OptTargetEnum;
import com.yixun.qfbao.model.enums.OptTypeEnum;
import com.yixun.qfbao.util.DateUtils;
import com.yixun.qfbao.util.exception.TServerException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * [文件名称]<br>
 * DepartmentServiceImpl.java<br>
 * <br>
 * [文件描述]<br>
 * 部门表 service interface impl<br>
 * <br>
 * [修改记录]<br>
 * 2017-01-04 11:28:59 创建 陶俊代码生成器<br>
 * 
 * @author 陶俊代码生成器
 * @version 1.00
 */
@Slf4j
@Service("departmentDao")
public class DepartmentDaoImpl implements DepartmentDao {

	@Autowired
	private DepartmentMapper mapper;
	@Autowired
	private CompanyMapper companyMapper;
	@Autowired
	private OperationLogMapper operationLogMapper;
	@Autowired
	private PartnerInfoMapper partnerInfoMapper;
	/**
	 * @param entity 搜索条件
	 * @param begin 分页开始行数[不包含]
	 * @param end 分页结束行数[包含]
	 * @return 分页记录
	 */
	@Transactional(readOnly = true)
	@Override
	public Page<Department> getPageModel(DepartmentDto entity,int begin,int end){
		Integer total = mapper.count(entity);
		List<Department> rows = mapper.list(entity,begin,end);
	    Page<Department> msr = new Page<Department>(total, rows);
		return msr;
	}

	/**
	 * 查询列表
	 * @param entity 搜索条件
	 * @return 分页记录
	 */
	@Override
	public List<Department> selectListByDto(DepartmentDto entity){
		return mapper.selectListByDto(entity);
	}

	@Override
	public List<Department> selectAllListByDto(DepartmentDto entity){
		return mapper.selectAllListByDto(entity);
	}
	/**
	 * 查询列表
	 * @param entity 搜索条件
	 * @return 分页记录
	 */
	@Override
	public List<DepartmentDto> selectList(DepartmentDto entity){
		return mapper.selectList(entity);
	}
	
	/**
	 * 查询单个
	 * @param entity 搜索条件
	 * @return 分页记录
	 */
	@Override
	public Department selectByDto(DepartmentDto entity){
		return mapper.selectByDto(entity);
	}
	
	/**
	 * @param id 搜索条件
	 * @return 分页记录
	 */
	@Override
	public Department selectById(Long id){
		if(id!=null){
			return mapper.selectById(id);
		}
		return null;
	}
	/**
	 * @param entity 新增记录的详细信息
	 * @return 新增行数
	 */
	@Override
	public DepartmentDto create(DepartmentDto entity) {
		if(Objects.isNull(entity.getCreateUserId())){
			entity.setCreateUserId(0L);
		}
		entity.setCreateTime(Calendar.getInstance().getTime());
		mapper.add(entity);
		return entity;
	}

	/**
	 * @param entity 更新记录的详细信息
	 * @return 更新行数
	 */
	@Override
	public int update(DepartmentDto entity) {
		entity.setUpdateTime(Calendar.getInstance().getTime());
		if(entity.getId().equals(entity.getParentId())){
			entity.setParentId(0L);
			log.info("dept id equals, update time: {}, entity: {}", Calendar.getInstance().getTime(), entity);
		}
		return mapper.edit(entity);
	}
	/**
	 * @param entity 更新记录的详细信息
	 * @return 更新行数
	 */
	@Override
	public int updateByMerchantId(DepartmentDto entity) {
		entity.setUpdateTime(Calendar.getInstance().getTime());
		return mapper.updateByMerchantId(entity);
	}
    
	/**
	 * @param entity 待删除的记录信息
	 * @return 删除行数
	 */
	@Override
	public int destroy(DepartmentDto entity) {
		if(entity.getId()!=null){
			//如果parentId为0时，要删除company表中的数据
			Department depart = mapper.selectById(entity.getId());
			if(depart.getParentId()==0){
				CompanyDto cDto = new CompanyDto();
				cDto.setId(depart.getMerchantId());
				companyMapper.del(cDto);
			}
		}
		return mapper.del(entity);
	}
	
	/**
	 * @param entity 新增或更新
	 * @return 新增行数
	 */
	@Override
	public int saveOrUpdate(DepartmentDto entity) {
		if(entity!=null&&entity.getId()!=null){
			return update(entity);
		}else{
			create(entity);
			return 1;
		}
	}
	
	/**
	 * @param entity 根据pojo搜索如果主键为空则返回它本身
	 * @return 一行记录或本身
	 */
	@Override
	public Department selectBy(Department entity) {
		if(entity!=null&&entity.getId()!=null){
			return mapper.selectById(entity.getId());
		}
		return entity;
	}
	
	/**
	 * @param entity 查询数量
	 * @return 记录数
	 */
	@Override
	public int count(DepartmentDto entity) {
		Integer total = mapper.count(entity);
		return total;
	}
	
	/**
	 * 查询列表
	 * @param entity 搜索条件
	 * @return 分页记录
	 */
	@Override
	public List<Department> distinctOrgNum(DepartmentDto entity){
		return mapper.distinctOrgNum(entity);
	}

	@Override
	public DepartmentDto getPrincipal(Long staffId) {
		return mapper.getPrincipal(staffId);
	}

	@Override
	public void delDept(Long id) {
		partnerInfoMapper.delPartnerByDeptId(id);//删除部门下的员工
		DepartmentDto childDeptDto = new DepartmentDto();
		childDeptDto.setParentId(id);
		List<Department> deptList = mapper.selectListByDto(childDeptDto);
		if(null != deptList && deptList.size() > 0){
			destroy(childDeptDto);
			for(Department dept: deptList){
				delDept(dept.getId());
			}
		}
	}

	@Override
	public boolean hasPartner(boolean flag,long id) {
		PartnerInfoDto piDto = new PartnerInfoDto();
		piDto.setDeptId(id);
		piDto.setStatus("1");
		//piDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
		int piCount = partnerInfoMapper.count(piDto);
		if(piCount > 0){
			flag =true;
		}else{
			DepartmentDto deptDto = new DepartmentDto();
			deptDto.setParentId(id);
			List<Department> deptList = mapper.selectListByDto(deptDto);
			if(null != deptList && deptList.size() > 0){
				for(Department dept: deptList){
					flag = hasPartner(flag,dept.getId());
				}
			}
		}
	return flag;
	}
	@Transactional
	@Override
	public Boolean mergeDept(DepartmentDto departmentDto){//accept
		boolean flag = true;
		try {
//			if (departmentDto.getMergeLevel().equals(departmentDto.getAcceptLevel())) {//同等级直接合并}
				//1.更新部门parentId
//				mapper.editParent(departmentDto.getMergeId(), departmentDto.getAcceptId());
				//2.删除部门
			//本部机构不能加到顶级
				Long mergeId = departmentDto.getMergeId();
				Long acceptId = departmentDto.getAcceptId();
				if("0".equals(departmentDto.getMergeLevel())){
					throw new TServerException("顶级部门不能合并");
				}

				checkChildDept(departmentDto,"不能合并到子部门");
				Department delDept = new Department();
				delDept.setDelFlag(DelFlagEnum.DEL.getNo());
				delDept.setId(mergeId);
				mapper.edit(delDept);
				//更新子部门到目标部门
				mapper.editParent(mergeId,acceptId);
				//3.更新人员表
				partnerInfoMapper.editParent(mergeId, acceptId);

		}catch (TServerException e){
			log.error("合并部门失败A: {}", e);
			throw  e;
		} catch (Exception e){
			log.error("合并部门失败B: {}", e);
			flag = false;
		}
		return flag;
	}

	@Override
	public Boolean changeDept(DepartmentDto departmentDto){
		boolean flag = true;
		try{
			Long mergeId = departmentDto.getMergeId();
			Long acceptId = departmentDto.getAcceptId();
			//已经转移到当前部门
			Department department = mapper.selectById(mergeId);
			if(department !=null && department.getParentId().equals(acceptId)){
				throw new TServerException("已经在该部门下，无法转移");
			}

			//本部机构不能加到顶级
			if("0".equals(departmentDto.getMergeLevel())){
				throw new TServerException("顶级部门不能转移");
			}
			if(departmentDto.getAcceptId().equals(departmentDto.getMergeId())){
				throw new TServerException("不能转移到自己部门");
			}
			//不能转移到自己的子部门
			checkChildDept(departmentDto,"不能转移到子部门");

			//1.将部门parent转移到目标
			Department dept = new Department();
			dept.setId(mergeId);
			dept.setParentId(acceptId);
			mapper.edit(dept);

		}catch (TServerException e){
			log.error("转移部门失败A: {}", e);
			throw e;
		} catch (Exception e){
			log.error("转移部门失败B: {}", e);
			flag = false;
		}
		return flag;
	}

	private void checkChildDept(DepartmentDto departmentDto,String msg){
		departmentDto.setParentId(departmentDto.getMergeId());
		List<DepartmentDto> list = mapper.selectList(departmentDto);
		for (DepartmentDto dto : list) {
			if (dto.getId().equals(departmentDto.getAcceptId())) {
				throw new TServerException(msg);
			} else {
				departmentDto.setMergeId(dto.getId());
				checkChildDept(departmentDto,msg);
			}
		}
	}

	@Override
	public List<Department> getDeptByCompCode(List<Department> deptList, String type) {
		List<Department> returnList = new ArrayList<Department>();
		if(null != deptList && deptList.size() > 0) {
			//获取顶级部门
			long parentId = 0L;
			for(Department dept: deptList) {
				if(parentId == dept.getParentId()) {
					parentId = dept.getId();
					break;
				}
			}
			if("1".equals(type)) {
				//获取门店: 第二级部门
				for(Department dept: deptList) {
					if(parentId == dept.getParentId()) {
						returnList.add(dept);
					}
				}
			}else if("2".equals(type)) {
				returnList = deptList;
			}
		}
		return returnList;
	}
	@Override
	public List<Department> getListByName(DepartmentDto departmentDto){
		return mapper.selectByName(departmentDto);
	}

	@Override
	public List<Department> getListByDev(DepartmentDto departmentDto,Long devId){
		if( null == devId){
			return new ArrayList<>();
		}
		List<Department> list = mapper.selectAgentDeptByDev(departmentDto,devId);
		return list;
	}
	@Override
	public List<Department> getListByParent(List<Department> parents){
		if( null == parents || parents.size() == 0){
			return new ArrayList<>();
		}
		List<Department> list = mapper.selectDeptByParents(parents);
		return list;
	}

    /**
     * 获取对接人（若当前部门无设置对接人则向上递归至顶级）
     * @param staffId
     * @return
     */
    @Override
    public DepartmentDto getPrincipalForWxMsg(Long staffId) {
	    if(staffId == null) {
	        throw new TServerException("经纪人ID不能为空！");
        }
        DepartmentDto departmentDto = mapper.getPrincipal(staffId);
	    if(departmentDto == null) {
	        return null;
        }
        if(StringUtils.isNotBlank(departmentDto.getPrincipalName())) {
	        return departmentDto;
        }
        //获取上级部门的对接人
        return getPrincipalByParent(departmentDto.getParentId());
    }

    private DepartmentDto getPrincipalByParent(Long parentId) {
        DepartmentDto departmentDto = new DepartmentDto();
        departmentDto.setId(parentId);
        DepartmentDto department = mapper.selectDeptByParent(departmentDto);
        if(department == null) {
            return null;
        }
        if (StringUtils.isNotBlank(department.getPrincipalName())) {
            return department;
        }
        return getPrincipalByParent(department.getParentId());
    }

    @Override
    public List<Department> getDeptByParent(Long parentId) {
        DepartmentDto departmentDto = new DepartmentDto();
        departmentDto.setParentId(parentId);
        List<Department> deptList = mapper.selectListByDto(departmentDto);
        if(null == deptList || deptList.size() == 0) {
            return null;
        }
        for (Department department : deptList) {
            List<Department> list = getDeptByParent(department.getId());
            if(null != list && list.size() > 0) {
                deptList.addAll(list);
            }
        }
        return deptList;
    }

	/**
	 * 获取部门所在层级 以及部门关系
	 * @param deptId
	 * @return
	 */
	@Override
	public int getDeptLevel(Long deptId){
		int deptLevel = 0;
		DepartmentDto departmentDto = new DepartmentDto();
		departmentDto.setId(deptId);
		List<Department> departmentList = mapper.selectAllListByDto(departmentDto);
		if(CollectionUtils.isEmpty(departmentList)){
			return deptLevel;
		}

		Department department = departmentList.get(0);
		if (department.getLayer() == 0){
			//直属于合作机构
			deptLevel = 1;
		}else if(department.getLayer() == 1){
			//直属于门店
			deptLevel = 2;
		}else if(department.getLayer() > 1){
			//直属于门店
			deptLevel = 3;
		}
		return deptLevel;
	}

	/**
	 * 人员所在层级，人员所在部门id，使用范围,只涉及门店和组别
	 * @param deptId
	 * @param decisionRegion
	 * @return
	 */
	@Override
	public List<Long> getDeptIdsWithLevel(int level,Long deptId,Integer decisionRegion){
		List<Long> deptIds;
        if(level == 1 || level == 0){
            return null;
        } else{
            Department thisDept = selectById(deptId);
            if(Objects.isNull(thisDept)){
                return null;
            }
            DepartmentDto departmentDto = new DepartmentDto();
            departmentDto.setPermissionCode(thisDept.getPermissionCode());
            departmentDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
            List<Department> departmentList = mapper.selectListByDto(departmentDto);
            deptIds = departmentList.stream()
                    .map(Department::getId)
                    .collect(Collectors.toList());
        }
		return deptIds;
	}

	@Override
	public List<Department> listDeptByParentId(Long companyId, Long deptId) {
		DepartmentDto dto = new DepartmentDto();
		dto.setMerchantId(companyId);
		List<Department> departments = mapper.selectListByDto(dto);
		Department selfDept = mapper.selectById(deptId);
		List<Department> subDepts = Lists.newArrayList();
		subDepts.add(selfDept);

		if (departments != null) {
			List<Long> deptIds = Lists.newArrayList();
			deptIds.add(deptId);
			for (int i = 0;i < deptIds.size(); i++) {
				for (Department department : departments) {
					if (department.getParentId().equals(deptIds.get(i))){
						deptIds.add(department.getId());
						subDepts.add(department);
					}
				}
			}
		}
		return subDepts;
	}

	@Override
	public List<Department> selectPartListByDto(DepartmentDto departmentDto) {
		return mapper.selectchangeListByDto(departmentDto);
	}

	@Override
	public List<DepartmentDto> selectPrincipalNameByCompany(DepartmentDto departmentDto) {
		return mapper.selectPrincipalNameByCompany(departmentDto);
	}
	
	/**
	 * 
	 * @param partnerId
	 * @return
	 */
	@Override
	public Map<String, Object> getPrincipalByPartnerId(Long partnerId){
		List<Map<String, Object>> principals = mapper.getPrincipalByPartnerId(partnerId);
		if(principals != null && principals.size() > 0) {
			return principals.get(0);
		}
		return null;
	}

	@Override
	public List<Department> selectListByPermissionCodes(DepartmentDto departmentDto) {
		return mapper.selectListByPermissionCodes(departmentDto);
	}

	@Override
	public List<Department> getChildDeptListByDeptId(Long deptId) {
		Department department = mapper.selectById(deptId);
		DepartmentDto departmentDto = new DepartmentDto();
		departmentDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
		departmentDto.setPermissionCodes(Arrays.asList(department.getPermissionCode()));
		return selectListByPermissionCodes(departmentDto);
	}
}
